package com.sherwin.sourdoughapp.socket

import android.widget.Toast
import com.orhanobut.logger.Logger
import com.sherwin.sourdoughapp.App
import com.vilyever.socketclient.SocketClient
import com.vilyever.socketclient.helper.SocketClientDelegate
import com.vilyever.socketclient.helper.SocketResponsePacket
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.subjects.BehaviorSubject

object SocketApiManager {

    private val mClient: MySocketClient = MySocketClient.getInstance()
    private var connectSubject: BehaviorSubject<SocketConnect> = BehaviorSubject.create()

    private val receiverList: MutableList<SocketReceiver> = mutableListOf()

    private var connectStatus : SocketConnect = SocketConnect.Disconnected

    fun initSocket() {
        mClient.localSocketClient.registerSocketClientDelegate(object : SocketClientDelegate {
            override fun onConnected(client: SocketClient?) {
                connectSubject.onNext(SocketConnect.Connected)
            }

            override fun onDisconnected(client: SocketClient?) {
                connectSubject.onNext(SocketConnect.Disconnected)

            }

            override fun onResponse(client: SocketClient?, responsePacket: SocketResponsePacket) {
                if (responsePacket.isHeartBeat) return
                Logger.v("onResponse => SocketClient: onResponse: ${responsePacket.message}")
                try {
                    val data = responsePacket.message
                    val keyWord = data.substringBefore(" ")
                    val json = data.substringAfter(" ")
                    onReceive(keyword = keyWord,json = json)
                } catch (e: Exception) {
                    App.instance.handleError(e)
                }
            }

        })
    }

    fun connect() {
        connectSubject.onNext(SocketConnect.Connecting)
        mClient.connect()
    }

    fun getConnectStatusObservable(): Observable<SocketConnect> {
        return connectSubject.hide()
            .map {
                connectStatus = it
                it
            }
    }

    fun send(data: String) {
        when (connectStatus) {
            SocketConnect.Disconnected -> {
                Toast.makeText(
                    App.instance.applicationContext,
                    "断开连接,请连接后重试",
                    Toast.LENGTH_SHORT
                ).show()
            }
            SocketConnect.Connecting -> {
                Toast.makeText(
                    App.instance.applicationContext,
                    "正在连接中,请连接后重试",
                    Toast.LENGTH_SHORT
                ).show()
            }
            SocketConnect.Connected -> {
                mClient.localSocketClient.sendData(data.toByteArray())
            }
        }
    }

    fun addReceiver(receiver: SocketReceiver) {
        synchronized(receiverList) {
            receiverList.add(receiver)
        }
    }

    fun removeReceiver(receiver: SocketReceiver) {
        synchronized(receiverList) {
            receiverList.remove(receiver)
        }
    }

    private fun onReceive(keyword : String,json : String){
        synchronized(receiverList){
            receiverList.filter { it.route == keyword }
                .forEach {
                    //todo
                    it.onReceive(json)
                }
        }
    }

    enum class SocketConnect {
        Connected,
        Disconnected,
        Connecting
    }
}